package com.jiegui.payinterface.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jiegui.payinterface.bean.DrawCashBean;
import com.jiegui.payinterface.bean.InterfacePaymentBean;
import com.jiegui.payinterface.bean.PaymentRes;
import com.jiegui.payinterface.bean.RefundBean;
import com.jiegui.payinterface.enums.PaymentStatus;
import com.jiegui.payinterface.handler.PaymentHandler;
import com.jiegui.payinterface.service.InterfacePayment;
import com.jiegui.pay.domain.InterfaceRequest;
import com.jiegui.pay.domain.OrderChannelInfo;
import com.jiegui.pay.service.InterfaceRequestService;
import com.jiegui.pay.service.OrderChannelInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 支付服务
 *
 * @author xueyou
 * @date 2021/3/11
 */
@Slf4j
@Service
public class InterfacePaymentImpl implements InterfacePayment {

    @Resource
    private Map<String, PaymentHandler> paymentHandlers;

    @Resource
    private OrderChannelInfoService orderChannelInfoService;

    @Resource
    private InterfaceRequestService interfaceRequestService;

    @Override
    public PaymentRes pay(InterfacePaymentBean interfacePaymentBean) {
        PaymentRes res = new PaymentRes();
        log.info("发起[付款]指令，请求参数：{}", interfacePaymentBean);

        // 查询接口配置
        OrderChannelInfo orderChannelInfoEntity = orderChannelInfoService.getOne(new QueryWrapper<OrderChannelInfo>().eq("code", interfacePaymentBean.getInterfaceCode()));

        InterfaceRequest request = interfaceRequestService.getOne(new QueryWrapper<InterfaceRequest>().eq("bill_code", interfacePaymentBean.getBillCode()));

        if (request != null && "FAILED".equals(request.getStatus())) {
            log.error("付款订单:[" + interfacePaymentBean.getBillCode() + "] 接口已处理");
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("付款订单已处理");
            return res;
        }

        // 记录接口请求
        InterfaceRequest interfaceRequest = new InterfaceRequest();
        interfaceRequest.setAmount(BigDecimal.valueOf( interfacePaymentBean.getAmount()));
        interfaceRequest.setBillCode(interfacePaymentBean.getBillCode());
       // interfaceRequest.setFlowId(VerifyCodeUtils.g());
        interfaceRequest.setInterfaceCode(interfacePaymentBean.getInterfaceCode());
        interfaceRequest.setStatus("UNKNOWN");
        interfaceRequest.setRequestTime(new Date());
        interfaceRequestService.save(interfaceRequest);

        // 获取通道处理类, 规定__分隔处理类和其他信息，例如 WX-PAYMENT__100006 走 WX-PAYMENT处理类
        String code = interfacePaymentBean.getInterfaceCode().replaceAll("__(.*)$", "");
        PaymentHandler paymentHandler = paymentHandlers.get(code);
        if (paymentHandler == null) {
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("未知支付渠道");
            return res;
        }
        interfaceRequest = interfaceRequestService.getById(interfaceRequest.getFlowId());

        // 組裝付款參數
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("billCode", interfacePaymentBean.getBillCode());
        reqMap.put("amount", String.valueOf(interfacePaymentBean.getAmount()));
        reqMap.put("payType", interfacePaymentBean.getPayType());
        reqMap.put("remark", interfacePaymentBean.getRemark());
        reqMap.put("notifyUrl", interfacePaymentBean.getNotifyUrl());
        reqMap.put("attach", interfacePaymentBean.getAttach());
        reqMap.put("userId", interfacePaymentBean.getUserId());
        reqMap.put("tradeConfigs", orderChannelInfoEntity.getTradeConfigs());
        reqMap.put("interfaceCode", interfacePaymentBean.getInterfaceCode());

        try {
            res = paymentHandler.pay(reqMap);
            log.info("[付款]指令，响应参数：{}  map=[{}]", res, res.toMap());
            if (PaymentStatus.SUCCESS.equals(res.getStatus())) {
                res.put("flowId",String.valueOf( interfaceRequest.getFlowId()));
                complete(res.toMap(), interfaceRequest);

                return res;
            }
        } catch (Exception e) {
            log.info("[付款]指令，请求异常", e);
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("付款异常");
        }

        return res;
    }

    @Override
    public PaymentRes query(Map<String, String> map) {
        PaymentRes res = new PaymentRes();
        String interfaceCode = map.get("interfaceCode");

        // 查询接口配置
        OrderChannelInfo orderChannelInfoEntity = orderChannelInfoService.getOne(new QueryWrapper<OrderChannelInfo>().eq("code", interfaceCode));
        String code = interfaceCode.replaceAll("__(.*)$", "");
        PaymentHandler paymentHandler = paymentHandlers.get(code);
        if (paymentHandler == null) {
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("未知接口通道");
            return res;
        }

        // 組裝查询參數
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("billCode", map.get("billCode"));
        reqMap.put("interfaceCode", interfaceCode);
        reqMap.put("tradeConfigs", orderChannelInfoEntity.getTradeConfigs());

        return paymentHandler.query(reqMap);
    }

    @Override
    public PaymentRes refund(RefundBean refundBean) {
        PaymentRes res = new PaymentRes();
        log.info("发起[退款]指令，请求参数：{}", refundBean);

        // 查询接口配置
        OrderChannelInfo orderChannelInfoEntity = orderChannelInfoService.getOne(new QueryWrapper<OrderChannelInfo>().eq("code", refundBean.getInterfaceCode()));

        // 获取通道处理类, 规定__分隔处理类和其他信息，例如 WX-PAYMENT__100006 走 WX-PAYMENT处理类
        String code = refundBean.getInterfaceCode().replaceAll("__(.*)$", "");
        PaymentHandler paymentHandler = paymentHandlers.get(code);
        if (paymentHandler == null) {
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("未知支付渠道");
            return res;
        }


        // 組裝付款參數
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("billCode", refundBean.getBillCode());
        reqMap.put("refundCode", refundBean.getRefundCode());
        reqMap.put("amount", String.valueOf(refundBean.getAmount()));
        reqMap.put("refundAmount", String.valueOf(refundBean.getRefundAmount()));
        reqMap.put("notifyUrl", refundBean.getNotifyUrl());
        reqMap.put("tradeConfigs", orderChannelInfoEntity.getTradeConfigs());

        try {
            res = paymentHandler.refund(reqMap);
            log.info("[退款]指令，响应参数：{}  map=[{}]", res, res.toMap());
            return res;
        } catch (Exception e) {
            log.info("[退款]指令，请求异常", e);
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("退款异常");
        }

        return res;
    }

    @Override
    public void complete(Map<String, String> map, InterfaceRequest interfaceRequest) {
        InterfaceRequest request = interfaceRequestService.getById(interfaceRequest.getFlowId());

        if (request == null || "UNKNOWN".equals(map.get("status"))) {
            return;
        }

        if (!"UNKNOWN".equals(request.getStatus())) {
            log.warn("接口订单:{} 已处理", request.getFlowId());
            return;
        }

        request.setStatus(map.get("status"));
        request.setCompleteTime(new Date());
        request.setResponseCode(map.get("responseCode"));
        request.setResponseMsg(map.get("responseMessage"));
        interfaceRequestService.updateById(request);
        log.info("[付款]指令处理完成: [{}]", request);
    }

    /**
     * 提现
     * @param bean bean
     * @return PaymentRes
     */
    @Override
    public PaymentRes drawcash(DrawCashBean bean) {
        PaymentRes res = new PaymentRes();
        log.info("发起[提现]指令，请求参数：{}", bean);

        // 查询接口配置
        OrderChannelInfo orderChannelInfoEntity = orderChannelInfoService.getOne(new QueryWrapper<OrderChannelInfo>().eq("code", bean.getInterfaceCode()));

        // 获取通道处理类, 规定__分隔处理类和其他信息，例如 WX-PAYMENT__100006 走 WX-PAYMENT处理类
        String code = bean.getInterfaceCode().replaceAll("__(.*)$", "");
        PaymentHandler paymentHandler = paymentHandlers.get(code);
        if (paymentHandler == null) {
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("未知支付渠道");
            return res;
        }
        Properties properties = JSON.parseObject( orderChannelInfoEntity.getTradeConfigs(), new TypeReference<Properties>() {});
        // 組裝付款參數
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("appid",properties.getProperty("appid"));
        reqMap.put("mchid",properties.getProperty("mchid"));
        reqMap.put("billCode",bean.getBillCode());
        reqMap.put("key",properties.getProperty("key"));
        reqMap.put("certPath",properties.getProperty("certPath"));
        reqMap.put("certPwd",properties.getProperty("certPwd"));
        reqMap.put("openid",bean.getOpenid());
        reqMap.put("amount", String.valueOf(bean.getAmount()));
        reqMap.put("ip", "127.0.0.1");
        reqMap.put("desc", bean.getDesc());
        try {
            res = paymentHandler.drawcash(reqMap);
            log.info("[提现]指令，响应参数：{}  map=[{}]", res, res.toMap());
            return res;
        } catch (Exception e) {
            log.info("[提现]指令，请求异常", e);
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("提现异常");
        }

        return res;
    }

    @Override
    public PaymentRes queryDrawCash(DrawCashBean  bean) {
        PaymentRes res = new PaymentRes();
        log.info("发起[提现查询]指令，请求参数：{}", bean);
        // 查询接口配置
        OrderChannelInfo orderChannelInfoEntity = orderChannelInfoService.getOne(new QueryWrapper<OrderChannelInfo>().eq("code", bean.getInterfaceCode()));

        // 获取通道处理类, 规定__分隔处理类和其他信息，例如 WX-PAYMENT__100006 走 WX-PAYMENT处理类
        String code = bean.getInterfaceCode().replaceAll("__(.*)$", "");
        PaymentHandler paymentHandler = paymentHandlers.get(code);
        if (paymentHandler == null) {
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("未知支付渠道");
            return res;
        }
        Properties properties = JSON.parseObject( orderChannelInfoEntity.getTradeConfigs(), new TypeReference<Properties>() {});
        // 組裝付款參數
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("appid",properties.getProperty("appid"));
        reqMap.put("mchid",properties.getProperty("mchid"));
        reqMap.put("key",properties.getProperty("key"));
        reqMap.put("partner_trade_no",bean.getBillCode());
        reqMap.put("certPath",properties.getProperty("certPath"));
        reqMap.put("certPwd",properties.getProperty("certPwd"));


        try {
            res = paymentHandler.queryDrawCash(reqMap);
            log.info("[提现查询]指令，响应参数：{}  map=[{}]", res, res.toMap());
            return res;
        } catch (Exception e) {
            log.info("[提现查询]指令，请求异常", e);
            res.setStatus(PaymentStatus.FAILURE);
            res.setResponseMessage("提现异常");
        }
        return res;
    }
}
